﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Fiddler;
using System.Collections;

namespace CSharp.Libs.Misc.JSON2Code
{
    /// <summary>forms
    /// 
    /// </summary>
    public partial class frmCodeGenerator : Form
    {
        #region declarations
        private Session _oSession = null;
        private Hashtable _htResponse = null;
        #endregion
        


        #region constructor / finalizer
        public frmCodeGenerator(
            Session oSession)
        {
            InitializeComponent();

            _oSession = oSession;

            _ShowData();
        }
        #endregion
        
        
        
        #region event handling
        private void chkOmmitResponseFbParameters_CheckedChanged(object sender, EventArgs e)
        {
            _ShowRequest();
        }
        
        private void btnReloadResponse_Click(object sender, EventArgs e)
        {
            _ShowResponse();
        }

        private void cmiRemoveValue_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem LVI in lvResponse.SelectedItems)
            {
                LVI.Remove();
            }
        }

        private void trvResponse_AfterSelect(object sender, TreeViewEventArgs e)
        {
            try
            {
                lvResponse.Items.Clear();

                _HashtableToListview(_GetHashtableByKey(_htResponse, e.Node.Text), "");
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        private void btnGenerateCode_Click(object sender, EventArgs e)
        {
            _GenerateCode();
        }
        #endregion
        
        
        
        #region private functions
        /// <summary>_ShowData</summary>
        /// <history>created  25.08.2011</history>
        private void _ShowData()
        {
            try
            {
                //Show Command
                String[] aryPhpCommand = _oSession.fullUrl.Split('/');
                lblPhpCommand.Text = aryPhpCommand[aryPhpCommand.GetUpperBound(0)];

                //Show request parameters
                _ShowRequest();

                //Show response
                _ShowResponse();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _ShowData(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>_ShowRequest</summary>
        /// <remarks>Shows request parameters in listview</remarks>
        /// <history>created  25.08.2011</history>
        private void _ShowRequest()
        {
            try
            {
                lvRequestParams.Items.Clear();

                String strRequest = _oSession.GetRequestBodyAsString();
                String[] strKeysValues = strRequest.Split('&');

                foreach (String strKV in strKeysValues)
                {
                    String[] strDE = strKV.Split('=');
                    if (strDE.GetUpperBound(0) > 0)
                    {
                        ListViewItem LVI = new ListViewItem();
                        LVI.Text = strDE[0];
                        LVI.SubItems.Add(strDE[1]);

                        if (!(chkOmmitResponseFbParameters.Checked && strDE[0].ToLower().StartsWith("fb_")))
                        {
                            lvRequestParams.Items.Add(LVI);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _ShowRequest(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>_ShowResponse</summary>
        /// <remarks>Shows all response keys in listview</remarks>
        /// <history>created  26.08.2011</history>
        /// <history>modified 16.02.2012: added null handling of response Hashtable</history>
        /// <history>modified 16.02.2012: added handling of main_src to be able to view seed</history>
        private void _ShowResponse()
        {
            try
            {
                //Clear response
                lvResponse.Items.Clear();

                //Get Response (if its MAIN_SRC, get seed)
                String strResponse = "";
                if (_oSession.fullUrl.ToLower().Contains("main_src.php"))
                {
                    strResponse = _getSeedJson();
                }
                else
                {
                    strResponse = _oSession.GetResponseBodyAsString();
                }

                //get response Hashtable
                _htResponse = JSON.JsonDecode(strResponse) as Hashtable;

                //show it
                if (_htResponse != null)
                {
                    _HashtableToTreeview(_htResponse);
                    _HashtableToListview(_htResponse, "");
                }
                else
                {
                    MessageBox.Show("Response is not a valid JSON string.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _ShowResponse(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>_getSeedJson</summary>
        /// <returns></returns>
        /// <history>created  16.02.2012</history>
        private string _getSeedJson()
        {
            try
            {
                string _strMainSrcSeedStart = "var seed";
                string _strMainSrcSeedEnd = ";var ";

                if (_oSession.fullUrl.ToLower().Contains("main_src.php"))
                {
                    String strMainPage = _oSession.GetResponseBodyAsString();

                    //get starting index of seed variabe in page's source
                    Int32 intStart = strMainPage.IndexOf(_strMainSrcSeedStart) + _strMainSrcSeedStart.Length + 1;

                    if (intStart > 0)
                    {
                        //get ending index of seed variable in page's source
                        Int32 intEnd = strMainPage.IndexOf(_strMainSrcSeedEnd, intStart + 1);

                        if (intEnd > intStart)
                        {
                            //get seed variable's string
                            String strSeed = strMainPage.Substring(intStart, intEnd - intStart);

                            if (strSeed != "")
                            {
                                return strSeed;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _getSeedJson(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return "";
        }

        /// <summary>_HashtableToTreeview</summary>
        /// <history>created  14.09.2011</history>
        private void _HashtableToTreeview(
            Hashtable htResponse)
        {
            try
            {
                trvResponse.Nodes.Clear();
                _HashtableToTreeNodeCollection(trvResponse.Nodes, htResponse);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _HashtableToTreeview(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>_HashtableToTreeNodeCollection</summary>
        /// <param name="nodeCollection"></param>
        /// <param name="htNodes"></param>
        /// <history>created  15.09.2011</history>
        private void _HashtableToTreeNodeCollection(
            TreeNodeCollection nodeCollection,
            Hashtable htNodes)
        {
            try
            {
                foreach (DictionaryEntry DE in htNodes)
                {
                    TreeNode tnHashNode = new TreeNode(DE.Key.ToString());
                    nodeCollection.Add(tnHashNode);

                    if (DE.Value is Hashtable)
                    {
                        _HashtableToTreeNodeCollection(tnHashNode.Nodes, DE.Value as Hashtable);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _HashtableToTreeNodeCollection(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        } 

        /// <summary>_HashtableToListview</summary>
        /// <remarks></remarks>
        /// <history>created  26.08.2011</history>
        private void _HashtableToListview(
            Hashtable htToListView,
            String strSubTableName)
        {
            try
            {
                if (htToListView != null)
                {
                    foreach (DictionaryEntry DE in htToListView)
                    {
                        String strType = "";
                        ListViewItem LVI = new ListViewItem();

                        if (DE.Value is Hashtable)
                        {
                            Hashtable htSub = DE.Value as Hashtable;
                            if (htSub.Count > 0)
                            {
                                LVI.Text = strSubTableName + DE.Key.ToString();
                                LVI.SubItems.Add("Hashtable...");
                                LVI.SubItems.Add(DE.Value.ToString());
                                lvResponse.Items.Add(LVI);

                                //get all Values recurseivly
                                _HashtableToListview(htSub, strSubTableName + DE.Key.ToString() + "_");
                            }
                        }
                        else if (DE.Value is ArrayList)
                        {
                            ArrayList aryValues = DE.Value as ArrayList;
                            foreach (object O in aryValues)
                            {
                            }
                        }
                        else
                        {
                            if (DE.Value is String)
                            {
                                strType = "String";
                            }
                            else if (DE.Value is Int32)
                            {
                                strType = "Int32";
                            }
                            else if (DE.Value is Int64)
                            {
                                strType = "Int64";
                            }
                            else if (DE.Value is UInt32)
                            {
                                strType = "UInt32";
                            }
                            else if (DE.Value is UInt64)
                            {
                                strType = "UInt64";
                            }
                            else if (DE.Value is Double)
                            {
                                strType = "Double";
                            }
                            else if (DE.Value is Boolean)
                            {
                                strType = "Boolean";
                            }
                            else
                            {
                                //Unknown
                                strType = "Unknown";
                            }

                            LVI.Text = strSubTableName + DE.Key.ToString();
                            LVI.SubItems.Add(strType);
                            if (DE.Value != null)
                            {
                                LVI.SubItems.Add(DE.Value.ToString());
                            }
                            else
                            {
                                LVI.SubItems.Add("null");
                            }
                            lvResponse.Items.Add(LVI);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _HashtableToListview(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>_GenerateCode</summary>
        /// <history>created  12.09.2011</history>
        private void _GenerateCode()
        {
            try
            {
                //Only need to act if ListViewItems exist
                if (lvResponse.Items.Count > 0)
                {
                    //Prepare input for CodeGenerator
                    String strCodeGeneratorInput = "";

                    foreach (ListViewItem LVI in lvResponse.Items)
                    {
                        strCodeGeneratorInput = String.Concat(strCodeGeneratorInput,
                            LVI.SubItems[0].Text, ",",
                            LVI.SubItems[1].Text, ",",
                            "false", Environment.NewLine);
                    }

                    //Create CodeGenerator and give him input
                    CodeGenerator CG = new CodeGenerator();
                    CG.CreateKeyConstants = true;
                    CG.CreateOnPropertyChanged = true;
                    CG.Input = strCodeGeneratorInput;

                    //Pop up window with output
                    frmCodeGeneratorOutput FCG = new frmCodeGeneratorOutput(CG);
                    FCG.ShowDialog();

                    //release references
                    FCG.Dispose();
                    FCG = null;
                    CG = null;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in _GenerateCode(): " + ex.Message, "Errorhandler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>_GetHashtableByKey</summary>
        /// <param name="htStart"></param>
        /// <param name="strKey"></param>
        /// <returns></returns>
        /// <history>created  23.09.2011</history>
        private Hashtable _GetHashtableByKey(
            Hashtable htStart,
            String strKey)
        {
            try
            {
                xxx
                    //TODO: Hier sollte ein fertiger Key erstellt werden der basiert auf den einzelnen Knotennamen.
                    //  z.B.: "cityStats|city10636". Dann kann per split und einer entsprechenden Schleife direkt auf
                    //  den korrekten Knoten zugegriffen werden ohne die rekursive Suche.
                foreach (DictionaryEntry DE in htStart)
                {
                    if (DE.Value is Hashtable)
                    {
                        if (DE.Key.ToString() == strKey)
                        {
                            return DE.Value as Hashtable;
                        }
                        else
                        {
                            Hashtable htNext = _GetHashtableByKey(DE.Value as Hashtable, strKey);

                            if (htNext != null)
                            {
                                return htNext;
                            }
                        }
                    }
                }

                return null;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Exception in _GetHashtableByKey", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
        }
        #endregion

        
        
        #region interface
        #region properties
        #endregion

        #region methods
        #endregion
        #endregion
    }
}
